package com.xul.crowd.config;

import com.google.gson.Gson;
import com.xul.crowd.constant.CrowdConstant;
import com.xul.crowd.exception.*;
import com.xul.crowd.util.CrowdUtil;
import com.xul.crowd.util.ResultEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author xul
 * @create 2021-07-23 12:11
 * @ControllerAdvice表示当前类是一个基于注解的异常处理器类 全局的异常处理器
 */
@ControllerAdvice
public class CrowdExceptionResolver {


    /**
     * 表是用户没有登录受保护资源的异常
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = Exception.class)
    public ModelAndView resolveAccessForbiddenException(Exception exception,
                                                              HttpServletRequest request,
                                                              HttpServletResponse response) throws IOException {
        String viewName = "system-error";
        return commonResolve(viewName, exception, request, response);
    }

    /**
     * 更新Admin这个账号时候保存或者更新抛出的这个异常
     *
     *所有异常走system-error页面的 已经在spring-web-mvc中配置过了
     *
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
//    @ExceptionHandler(value = LoginAcctAlreadyInUseForUpdateException.class)
//    public ModelAndView resolveLoginAcctAlreadyInUseForUpdateException(LoginAcctAlreadyInUseForUpdateException exception,
//                                                              HttpServletRequest request,
//                                                              HttpServletResponse response) throws IOException {
//        String viewName = "system-error";
//        return commonResolve(viewName, exception, request, response);
//    }

    @ExceptionHandler(value = RoleAcctAlreadyInUseException.class)
    public ModelAndView resolveRoleAcctAlreadyInUseException(RoleAcctAlreadyInUseException exception,
                                                              HttpServletRequest request,
                                                              HttpServletResponse response) throws IOException {
        String viewName = "role/role-page";
        return commonResolve(viewName, exception, request, response);
    }

    /**
     * 保存更新Admin这个账号时候保存或者更新抛出的这个异常
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = LoginAcctAlreadyInUseException.class)
    public ModelAndView resolveLoginAcctAlreadyInUseException(LoginAcctAlreadyInUseException exception,
                                                              HttpServletRequest request,
                                                              HttpServletResponse response) throws IOException {
        String viewName = "admin/admin-add";
        return commonResolve(viewName, exception, request, response);
    }

    /**
     * 登录失败异常
     *
     * @param exception
     * @param request
     * @param response
     * @return
     */
    @ExceptionHandler(value = LoginFailedException.class)
    public ModelAndView resolveLoginFailedException(LoginFailedException exception,
                                                    HttpServletRequest request,
                                                    HttpServletResponse response) throws IOException {
        String viewName = "admin/admin-login";
        return commonResolve(viewName, exception, request, response);
    }


    /**
     * 通用处理异常方法
     *
     * @param viewName
     * @param exception
     * @param request
     * @param response
     * @return
     */
    private ModelAndView commonResolve(String viewName, Exception exception, HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 1.判断当前请求的类型
        boolean judgeResult = CrowdUtil.judgeRequestType(request);
        // 2.如果是ajax请求
        if (judgeResult) {
            // 3.创建ResultEntity对象
            ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
            // 4.创建Gson对象
            Gson gson = new Gson();
            // 5.将resultEntity对象转换为JSON字符串
            String json = gson.toJson(resultEntity);

            // 6.将JSON字符串作为响应体返回给浏览器
            response.getWriter().write(json);

            // 7.由于上面已经通过原生的response对象返回了响应,所以就不提供ModelAndView对象
            return null;
        }
        // 8.如果不是Ajax请求则创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();
        // 9.将Exception对象存入模型
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION, exception);
        // 10.设置对应视图的名称
        modelAndView.setViewName(viewName);
        // 11.返回modelAndView对象
        return modelAndView;
    }

    /**
     * @param exception
     * @param request
     * @return
     * @ExceptionHandler 将一个具体的异常类和一个方法关联起来
     */
//    @ExceptionHandler(value = NullPointerException.class)
//    public ModelAndView resolveNumPointerException(
//
//            // 实际捕获到的异常类型
//            NullPointerException exception,
//            // 当前请求的对象
//            HttpServletRequest request,
//            // 当前响应对象
//            HttpServletResponse response) throws IOException {
//        // 1.判断当前请求的类型
//        boolean judgeResult = CrowdUtil.judgeRequestType(request);
//        // 2.如果是ajax请求
//        if (judgeResult) {
//            // 3.创建ResultEntity对象
//            ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
//            // 4.创建Gson对象
//            Gson gson = new Gson();
//            // 5.将resultEntity对象转换为JSON字符串
//            String json = gson.toJson(resultEntity);
//            // 6.将JSON字符串作为响应体返回给浏览器
//            response.getWriter().write(json);
//            // 7.由于上面已经通过原生的response对象返回了响应,所以就不提供ModelAndView对象
//            return null;
//        }
//        // 8.如果不是Ajax请求则创建ModelAndView对象
//        ModelAndView modelAndView = new ModelAndView();
//        // 9.将Exception对象存入模型
//        modelAndView.addObject("exception", exception);
//        // 10.设置对应视图的名称
//        modelAndView.setViewName("system-error");
//        // 11.返回modelAndView对象
//        return modelAndView;
//
//    }
}
